/**
 * @author Federico Consoli
 *
 * Released under GNU GPLv3 (http://www.gnu.org/licenses/gpl-3.0.txt)
 */

#include "lettori_scrittori.h"

using namespace std;

Lettori_scrittori::Lettori_scrittori(){
        nreaders=0;
        if(pthread_mutex_init(&lettura,NULL))throw 9;
        if(pthread_mutex_init(&scrittura,NULL))throw 9;
        if(pthread_mutex_init(&counter,NULL))throw 9;
        
        
    }
    Lettori_scrittori::~Lettori_scrittori(){
        
        if(pthread_mutex_destroy(&lettura))throw 14;
        if(pthread_mutex_destroy(&scrittura))throw 14;
        if(pthread_mutex_destroy(&counter))throw 14;
    }
    
    
    void Lettori_scrittori::leggi_begin(){
        int prev;
        
        pthread_mutex_lock(&scrittura);
        pthread_mutex_lock(&counter);
            prev = nreaders;
            nreaders = nreaders + 1;
        pthread_mutex_unlock(&counter);
         if (prev == 0)  pthread_mutex_lock(&lettura);
        pthread_mutex_unlock(&scrittura);
     }   
    //leggi..
    void Lettori_scrittori::leggi_end()   { 
        
        int current;
        pthread_mutex_lock(&counter);
         nreaders = nreaders - 1;
          current = nreaders;
          pthread_mutex_unlock(&counter);
          if (current == 0) pthread_mutex_unlock(&lettura); //L'ultimo chiude la porta :D
               
    }
     void Lettori_scrittori::scrivi_begin(){
        pthread_mutex_lock(&scrittura);
                pthread_mutex_lock(&lettura); //Si blocca quando ho 0 lettori all'inizio e gli altri lettori  che 
                //Devono chiudere la leggi, l'ultimo manderà una signal al lettura che abiliterà alla scrittura
                //In poche parole attendo che abbiano finito di leggere, l'ultimo mi da il via
                
                pthread_mutex_unlock(&lettura); //Lo posso sbloccare, nessun thread è in wait su lettura
                                                //dato che prima ho bloccato scrittura
            }
     
      //scrivi....
        void Lettori_scrittori::scrivi_end(){        
       
        pthread_mutex_unlock(&scrittura);
        
    }